home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / CUSTOM_C.C < prev    next >
C/C++ Source or Header  |  1990-03-07  |  20KB  |  661 lines

  1. #include "StdInclude.h"    
  2.  
  3.  
  4. /* NB: There is little or no error checking for bad handle, pointers, etc. Perhaps there should        */
  5. /*        be but it is unclear what should be done if there is an error. Exit? Call DebugStr?            */
  6. /*     Perhaps I should try and check my own region handles and rect (frame, empty, etc.) since        */
  7. /*      it is my responsibility to check these but even if I made a mistake, what should I do?        */
  8. /*     There is no good way to get an error back to the programmer.                                    */
  9.  
  10. typedef short            int16;
  11. typedef long            int32;
  12. typedef unsigned short    uint16;
  13. typedef unsigned long    uint32;
  14.  
  15. /* at last! CDEF stuff */
  16. typedef struct cntl_rgns         /* data structure for regions in control, handle to this stored in contrlData field */
  17. {
  18.     RgnHandle    frame;
  19.     RgnHandle    empty;
  20.     RgnHandle    full;
  21.     RgnHandle    indicator;
  22.     Rect        ind_rect;
  23. } cntl_rgns;
  24.  
  25. typedef cntl_rgns *         cntl_rgns_ptr;
  26. typedef cntl_rgns_ptr *        cntl_rgns_hdl;
  27.  
  28. typedef struct thumb_lim {
  29. /* fubar type struct used by ctl manager for showing limits of "thumb" dragging        */
  30.     Rect    limitRect, slopRect;
  31.     int16    axis;
  32. } thumb_lim;
  33.  
  34.  
  35. /* prototypes for custom stuff */
  36. void    CDEF_draw_cntl(ControlHandle,int32);
  37. void    CDEF_buttons(ControlHandle);
  38. void    CDEF_frame(ControlHandle);
  39. void    CDEF_indicator(ControlHandle);
  40. void    CDEF_disabled_cntl(ControlHandle);
  41. Point    CDEF_ind_endpt(ControlHandle, int16);
  42. int32    CDEF_test_cntl(ControlHandle, int32);
  43. void    CDEF_calc_rgns_cntl(ControlHandle, int32);
  44. void    CDEF_all_rgns (ControlHandle, cntl_rgns_hdl);
  45. void    CDEF_init_cntl (ControlHandle);
  46. void    CDEF_disp_cntl (ControlHandle);
  47. int32    CDEF_drag_cntl (ControlHandle,int32);
  48. void    CDEF_pos_cntl (ControlHandle,int16,int16);
  49. void    CDEF_thumb_cntl (ControlHandle,int32);
  50. Point    CDEF_find_center (ControlHandle);
  51. int16    CDEF_value_to_angle ( ControlHandle, int16 );
  52. int16    CDEF_angle_to_value ( ControlHandle, int16 );
  53. void    CDEF_ind_rgn ( ControlHandle, int16, RgnHandle );
  54.  
  55. #define    SysFontSiz    12
  56. #define ENABLED        0
  57. #define    DISABLED    255
  58. #define    ALL            0
  59. #define    TITLE        1
  60. #define INDBITMASK    0x80000000
  61. #define INDBYTECLEAR 0x00FFFFFF
  62. #define    NO_CONSTRAINT 0
  63. #define RETURN
  64.  
  65.  
  66. pascal int32    main (varCode,theCtl,message,param)
  67. int16             varCode;
  68. ControlHandle    theCtl;
  69. int16            message;
  70. int32            param;
  71. {
  72.     int32        retn_value;
  73.     GrafPtr        oldPort;
  74.     signed char    hState;
  75.     
  76.     /* custom control to implement a gas gauge */
  77.     hState = HGetState ( (Handle)theCtl );
  78.     HLock ( (Handle)theCtl );
  79.     
  80.     GetPort ( &oldPort );
  81.     SetPort ( (**theCtl).contrlOwner );
  82.     retn_value = (int32)0;
  83.     
  84.     switch (message)
  85.     {
  86.         case drawCntl:
  87.             CDEF_draw_cntl ( theCtl, param );
  88.             break;
  89.         case testCntl:
  90.             retn_value = CDEF_test_cntl ( theCtl, param );
  91.             break;
  92.         case calcCRgns:
  93.             CDEF_calc_rgns_cntl ( theCtl, param );
  94.             break;
  95.         case initCntl:
  96.             CDEF_init_cntl ( theCtl );
  97.             break;
  98.         case dispCntl:
  99.             CDEF_disp_cntl ( theCtl );
  100.             break;
  101.         case dragCntl:
  102.             retn_value = CDEF_drag_cntl ( theCtl, param );
  103.             break;
  104.         case posCntl: 
  105.             CDEF_pos_cntl ( theCtl, LoWord ( param ), HiWord ( param ) );
  106.             break;
  107.         case thumbCntl:
  108.             CDEF_thumb_cntl ( theCtl, param );
  109.             break;
  110.         case autoTrack:
  111.             break;
  112.     }
  113.     SetPort ( oldPort );
  114.     
  115.     HSetState ( theCtl, hState );
  116.     return ( retn_value );
  117. }
  118.  
  119.  
  120. Point    CDEF_find_center ( the_cntl )
  121. ControlHandle    the_cntl;
  122. {
  123.     Rect    cntl_rect;
  124.     Point    center;
  125.     
  126.     /* return the center of the control rectangle */
  127.     cntl_rect = (**the_cntl).contrlRect;
  128.     SetPt ( ¢er, cntl_rect.left+(cntl_rect.right-cntl_rect.left)/2, cntl_rect.top+(cntl_rect.bottom-cntl_rect.top)/2 );
  129.     return ( center );
  130. }
  131.  
  132.  
  133. void    CDEF_draw_cntl(the_cntl,param)
  134. ControlHandle    the_cntl;
  135. int32            param;
  136. {
  137.     PenState     ps;
  138.     int16        radius;
  139.     
  140.     if ((**the_cntl).contrlVis == 0)        /* invisible so don't draw */
  141.         RETURN;
  142.     GetPenState(&ps);                        /* to save against any hiliting */
  143.  
  144.     switch( param )
  145.     {
  146.         default:                            /* this is necessary because of Control Manager bug:    */
  147.                                             /* CM calls me with part code == 255?!                    */
  148.         case ALL:
  149.             CDEF_frame(the_cntl);
  150.             CDEF_buttons(the_cntl);
  151.             CDEF_indicator(the_cntl);
  152.             /* CDEF_cntl_draw_title(the_cntl);  add this later */
  153.             break;
  154.         case inThumb:
  155.             CDEF_indicator (the_cntl);
  156.             break;
  157.         case inUpButton:
  158.         case inDownButton:
  159.             CDEF_buttons(the_cntl);
  160.             break;
  161.     }
  162.     if ((**the_cntl).contrlHilite == DISABLED)
  163.         CDEF_disabled_cntl(the_cntl);
  164.     SetPenState(&ps);        /* no side effects in grafport */
  165. }
  166.  
  167. void    CDEF_buttons(the_cntl)
  168. ControlHandle    the_cntl;    /* assumed to be locked */
  169. {
  170.     Point        the_center;
  171.     Rect        cntl_rect;
  172.     int16        radius;
  173.     int16        old_text_size;
  174.     Style        old_text_face;
  175.     int16        old_text_font;
  176.     PenState     ps;
  177.     RgnHandle    but_rgn_hdl;
  178.     GrafPtr        cur_port;
  179.     
  180.     /* check hiliting and if title is hilited, draw it so */
  181.     GetPenState ( &ps );
  182.     GetPort ( &cur_port );
  183.     old_text_size = cur_port->txSize;
  184.     old_text_font = cur_port->txFont;
  185.     old_text_face = cur_port->txFace;
  186.     TextSize ( 12 );                        /* default size        */
  187.     TextFont ( 0 );                            /* default font        */
  188.     TextFace ( 0 );
  189.     
  190.     the_center = CDEF_find_center ( the_cntl );
  191.     
  192.     /* draw the buttons - boxed '0' and '1' for now */
  193.     cntl_rect = (**the_cntl).contrlRect;
  194.     if ( cntl_rect.bottom - cntl_rect.top > cntl_rect.right - cntl_rect.left )
  195.         radius = the_center.h - cntl_rect.left;
  196.     else
  197.         radius = the_center.v - cntl_rect.top;
  198.     but_rgn_hdl = (**(cntl_rgns_hdl)(**the_cntl).contrlData).empty;
  199.     EraseRgn ( but_rgn_hdl );                /* clear out the old            */
  200.     MoveTo ( the_center.h, the_center.v );
  201.     Move ( -(radius-2), 0 );
  202.     PenSize ( 2, 2 );
  203.     Line( 5, 0 );                            /* hash mark                                    */
  204.     PenSize ( 1, 1 );
  205.     Move( 7, 5 );                            /* text is above an to the right of penpos        */
  206.     DrawChar('0');
  207.     FrameRgn ( but_rgn_hdl );                /* box the text                    */
  208.     if ((**the_cntl).contrlHilite == inUpButton)
  209.         InvertRgn ( but_rgn_hdl );
  210.         
  211.     /* draw the full indicator */
  212.     but_rgn_hdl = (**(cntl_rgns_hdl)(**the_cntl).contrlData).full;
  213.     EraseRgn ( but_rgn_hdl );                /* erase the old                */
  214.     MoveTo ( the_center.h, the_center.v );
  215.     Move ( (radius-8), 0 );
  216.     PenSize ( 2, 2 );
  217.     Line( 5, 0 );                            /* hash mark                                    */
  218.     PenSize ( 1, 1 );
  219.     
  220.     Move( -(10+CharWidth('1')), 5 );
  221.     DrawChar ( '1' );        
  222.     FrameRgn ( but_rgn_hdl );
  223.     if ((**the_cntl).contrlHilite == inDownButton)
  224.         InvertRgn ( but_rgn_hdl );
  225.  
  226.     /* draw the 1/2 full mark  */
  227.     MoveTo(the_center.h,the_center.v-(radius-8));
  228.     PenSize ( 2, 2 );
  229.     Line( 0, -5 );
  230.     PenSize ( 1, 1 );
  231.  
  232.     TextSize ( old_text_size );            /* restore text size before leaving */
  233.     TextFont ( old_text_font );            /* restore text font before leaving */
  234.     TextFace ( old_text_face );            /* restore text face before leaving */
  235.     SetPenState ( &ps );                /* restore penstate before leaving  */
  236. }
  237.  
  238. void    CDEF_frame(the_cntl)
  239. ControlHandle    the_cntl;    /* assumed to be locked */
  240. {
  241.     PenState    ps;
  242.     
  243.     GetPenState ( &ps );
  244.     PenSize ( 2, 2 );
  245. /*    EraseRgn ( (**((cntl_rgns_hdl)(**the_cntl).contrlData)).frame );*/
  246.     FrameRgn ( (**((cntl_rgns_hdl)(**the_cntl).contrlData)).frame );
  247.     SetPenState ( &ps );
  248. }
  249.  
  250. void    CDEF_indicator ( the_cntl )
  251. ControlHandle    the_cntl;    /* assumed to be locked */
  252. {
  253.     RgnHandle     ind_rgn_hdl;
  254.     Rect        ind_rect;
  255.     
  256.     ind_rect = (**((cntl_rgns_hdl)(**the_cntl).contrlData)).ind_rect;
  257.     EraseOval ( &ind_rect );                    /* clear out old indicator                                    */
  258.     ind_rgn_hdl = (**((cntl_rgns_hdl)(**the_cntl).contrlData)).indicator;
  259.     CDEF_ind_rgn ( the_cntl, (**the_cntl).contrlValue, ind_rgn_hdl );
  260.     if ((**the_cntl).contrlHilite == inThumb)
  261.         PaintRgn ( ind_rgn_hdl );
  262.     else
  263.         FrameRgn ( ind_rgn_hdl );
  264. }
  265.  
  266.  
  267. void    CDEF_disabled_cntl(the_cntl)
  268. ControlHandle    the_cntl;        /* assumed to be locked */
  269. {
  270.     PenState    ps;
  271.     Pattern        gray_pat;
  272.     
  273.     GetPenState(&ps);
  274.     GetIndPattern ( &gray_pat, sysPatListID, 4 ); 
  275.     PenPat(gray_pat);
  276.     PenMode(patBic);
  277.     PaintOval(&(**the_cntl).contrlRect);
  278.     SetPenState(&ps);
  279. }
  280.  
  281.  
  282. Point    CDEF_ind_endpt ( the_ctl, value )
  283. ControlHandle    the_ctl;
  284. int16            value;
  285. {
  286.     int16    angle, radius;
  287.     Fixed    radians, temp1, temp2;
  288.     Point    endpt, the_center;
  289.     Rect    ind_rect;
  290.     Fract    trig_val;
  291.     
  292.     /* calculates the endpt of the indicator of the control    */
  293.     ind_rect = (**(cntl_rgns_hdl)(**the_ctl).contrlData).ind_rect;
  294.     the_center = CDEF_find_center ( the_ctl );
  295.     radius = ind_rect.right - the_center.h;
  296.     angle = CDEF_value_to_angle ( the_ctl, value );                    /* convert it to degrees counterclockwise    */
  297.     radians = FixDiv ( Long2Fix ( (long)angle ), Long2Fix ( 45L ) );        /* now divide by 90 to find out how many Pi/4's there are     */
  298.     radians = FixMul (     FixAtan2 ( 1L, 1L ), radians );                        /* FixATan2(1,1) == Pi/4        */
  299.     temp1 = Frac2Fix ( FracCos ( radians ) );
  300.     temp2 = Long2Fix ( (long)radius );
  301.     endpt.h = (int16)Fix2Long ( FixMul ( temp1, temp2 ) );
  302.     temp1 = Frac2Fix ( FracSin ( radians ) );
  303.     endpt.v = (int16)Fix2Long ( FixMul ( temp1, temp2 ) );            /* to move from the center out by r*cos(theta), r*sin(theta)    */
  304.     AddPt ( the_center, &endpt );
  305.     MoveTo ( endpt.h, endpt.v );                                            
  306.     return ( endpt );
  307. }
  308.  
  309. int32    CDEF_test_cntl(the_cntl,param)
  310. ControlHandle    the_cntl;
  311. int32            param;
  312. {
  313.     cntl_rgns_hdl    my_cntl_rgns;    /* handle of control's custom regions    */
  314.     int16            the_angle,cur_angle;
  315.     Point            the_point,cur_pt;
  316.     Rect            ind_rect;
  317.     
  318.     /* this routine test where the mouse was down as passed in the_point and returns the */
  319.     /* part code for the part of the control referenced by the_cntl                         */
  320.     
  321.     if ((**the_cntl).contrlHilite == DISABLED)        /* inactive control so return a 0 to indicatew nothing selected */
  322.         RETURN( 0L );
  323.     
  324.     SetPt(&the_point,LoWord(param),HiWord(param));
  325.     my_cntl_rgns =     (cntl_rgns_hdl)(**the_cntl).contrlData;        /* handle to my data structure for control */
  326.     
  327.     if ( !PtInRgn( the_point, (**my_cntl_rgns).frame ) )
  328.         return ( 0L );        /* if point is outside of control frame, return 0 to indicate nothing hit */
  329.  
  330.     if ( PtInRgn( the_point, (**my_cntl_rgns).empty ) )
  331.         return ( (long)inUpButton );        /* because the '0' maps to scrollbar up button */
  332.  
  333.     if ( PtInRgn ( the_point,(**my_cntl_rgns).full ) )
  334.         return ( (long)inDownButton );    /* because the '1' maps to scrollbar down button */
  335.  
  336.     if ( PtInRgn ( the_point,(**my_cntl_rgns).indicator ) )
  337.         return ( (long)inThumb );        /* because arrow maps to scrollbar thumb */
  338.     
  339.     /* now, if none of the above, check for page_up/down */
  340.     /* first check to see if it is area above and to right of E or above and left of F */
  341.     ind_rect = (**(cntl_rgns_hdl)(**the_cntl).contrlData).ind_rect;
  342.     InsetRect ( &ind_rect, 7, 7 );
  343.     PtToAngle( &ind_rect, the_point, &the_angle );
  344.     if ( the_angle < 270 && the_angle > 90 )
  345.         return ( 0L );                /* nohit because point is outside "active area" of control */
  346.     cur_pt = CDEF_ind_endpt ( the_cntl, (**the_cntl).contrlValue );
  347.     PtToAngle ( &ind_rect, cur_pt, &cur_angle );
  348.  
  349.     /* now check to see if in page_up or page_down */
  350.     the_angle = (the_angle+90) % 360;    /* to rotate angles to avoid angle "wrap" at 0 degrees */
  351.     cur_angle = (cur_angle+90) % 360;     /* to rotate angles to avoid angle "wrap" at 0 degrees */
  352.     if ( the_angle<cur_angle )
  353.         return ( (long)inPageUp );        /* becuase point to left of indicator corresponds to scrollbar page up */
  354.     else
  355.         return ( (long)inPageDown );        /* becuase point to right of indicator corresponds to scrollbar page down */
  356. }
  357.  
  358. int16    CDEF_value_to_angle ( the_ctl, the_value )
  359. ControlHandle    the_ctl;
  360. int16            the_value;
  361. {
  362.     int16    min_value, max_value;
  363.     
  364.     /* return the associated angle for a value within the_ctl    */
  365.     min_value = (**the_ctl).contrlMin;
  366.     max_value = (**the_ctl).contrlMax;
  367.     if (max_value-min_value == 0 )
  368.         return ( 0 );
  369.     else
  370.         return ( 180 + (the_value - min_value)*180/(max_value-min_value) );
  371. }
  372.  
  373.  
  374. int16    CDEF_angle_to_value ( the_ctl, the_angle )
  375. ControlHandle    the_ctl;
  376. int16            the_angle;
  377. {
  378.     int16    mid_value, min_value, max_value;
  379.     
  380.     /* convert an angle to a value for the given control    */
  381.     min_value = (**the_ctl).contrlMin;
  382.     max_value = (**the_ctl).contrlMax;
  383.     mid_value = (max_value+min_value)/2;
  384.     
  385.     if ( the_angle <= 90 )
  386.         return ( mid_value + the_angle*(max_value-mid_value)/90 );
  387.     else
  388.     {
  389.         if ( the_angle >= 270 )
  390.             return ( mid_value - ((360 - the_angle) * (mid_value-min_value))/90 );
  391.         else
  392.             return ( min_value );    /* really an error, but what are ya gonna do? */
  393.     }
  394. }
  395.  
  396.  
  397. void    CDEF_calc_rgns_cntl( the_cntl, param )
  398. ControlHandle    the_cntl;
  399. int32            param;
  400. {
  401.     /* calculate the control region or indicator region                                             */
  402.     /* may want to add control title later on                                                         */
  403.     
  404.     if (BitAnd(param, INDBITMASK ))            /* if this bit is set, only indicator rgn is desired    */
  405.     {
  406.         param = BitAnd ( param, INDBYTECLEAR );
  407.         CDEF_ind_rgn ( the_cntl, (**the_cntl).contrlValue, (**((cntl_rgns_hdl)(**the_cntl).contrlData)).indicator );
  408.         CopyRgn( (**((cntl_rgns_hdl)(**the_cntl).contrlData)).indicator, (RgnHandle)param );
  409.     }
  410.     else                                    /* entire control region                                */
  411.     {
  412.         CDEF_all_rgns ( the_cntl, (cntl_rgns_hdl)(**the_cntl).contrlData );
  413.         CopyRgn ( (RgnHandle)param, (**((cntl_rgns_hdl)(**the_cntl).contrlData)).frame );
  414.     }
  415. }
  416.  
  417.  
  418. void    CDEF_all_rgns ( the_cntl, the_cntl_rgns )
  419. ControlHandle    the_cntl;
  420. cntl_rgns_hdl    the_cntl_rgns;
  421. {
  422.     FontInfo    font_info;
  423.     Rect        the_cntl_rect, the_trect;
  424.     Point        the_center;
  425.     Point        indicator;
  426.     int16        width, height;
  427.     
  428.     /* calculate or recalculate regions specific to this control                    */
  429.     GetFontInfo (&font_info);
  430.  
  431.     HLock ( (Handle)the_cntl_rgns );
  432.  
  433.     the_cntl_rect = (**the_cntl).contrlRect;
  434.     the_center = CDEF_find_center ( the_cntl );
  435.  
  436.     /* calculate "empty" button region */
  437.     SetRect ( &the_trect, the_cntl_rect.left+11, the_center.v-10, the_cntl_rect.left+10+font_info.widMax, the_center.v+10);
  438.     SetEmptyRgn ( (**the_cntl_rgns).empty );
  439.     OpenRgn();
  440.     FrameRect ( &the_trect );
  441.     CloseRgn ( (**the_cntl_rgns).empty );
  442.     
  443.     /* calculate "full" button region */
  444.     SetRect ( &the_trect, the_cntl_rect.right-9-font_info.widMax, the_center.v-10, the_cntl_rect.right-10, the_center.v+10);
  445.     SetEmptyRgn ( (**the_cntl_rgns).full );
  446.     OpenRgn();
  447.     FrameRect ( &the_trect );
  448.     CloseRgn ( (**the_cntl_rgns).full );
  449.  
  450.     /* calculate indicator rectangle */
  451.     width = the_cntl_rect.right - the_cntl_rect.left;
  452.     height = the_cntl_rect.bottom - the_cntl_rect.top;
  453.     if ( width > height )
  454.         SetRect ( &(**the_cntl_rgns).ind_rect, the_center.h-height/2, the_center.v-height/2, the_center.h+height/2, the_center.v+height/2 );
  455.     else
  456.         SetRect ( &(**the_cntl_rgns).ind_rect, the_center.h-width/2, the_center.v-width/2, the_center.h+width/2, the_center.v+width/2 );
  457.     InsetRect ( &(**the_cntl_rgns).ind_rect, 25, 25 );
  458.     
  459.     /* calculate the indicator regions    */
  460.     CDEF_ind_rgn ( the_cntl, (**the_cntl).contrlValue, (**the_cntl_rgns).indicator );
  461.     
  462.     /* calculate control frame    */
  463.     SetEmptyRgn ( (**the_cntl_rgns).frame );
  464.     OpenRgn();
  465.     FrameOval ( &(**the_cntl).contrlRect );
  466.     CloseRgn ( (**the_cntl_rgns).frame );
  467.  
  468.     HUnlock ( (Handle)the_cntl_rgns );
  469. }
  470.  
  471.  
  472. void    CDEF_ind_rgn ( the_cntl, value, the_rgn )
  473. ControlHandle    the_cntl;
  474. int16            value;
  475. RgnHandle        the_rgn;
  476. {
  477.     Point        the_center, the_end, base_pt;
  478.     Rect        ind_rect;
  479.     int16        the_angle;
  480.     
  481.     /* calculate indicator region                                                                         */
  482.     the_center = CDEF_find_center ( the_cntl );
  483.     the_angle = CDEF_value_to_angle ( the_cntl, value );
  484.     if ( the_angle < 240 || the_angle > 300 )                /* set up base of indicator based on angle    */
  485.     {                                                        /* if angle more horizontal, make base vert */
  486.         SetPt ( &base_pt, the_center.h, the_center.v-5 );
  487.         the_center.v += 5;
  488.     }
  489.     else                                                    /* else make it more horizontal                */
  490.     {                                                        /* this horsing around keeps the indicator    */
  491.         SetPt ( &base_pt, the_center.h+5, the_center.v );    /* from disappearing                        */
  492.         the_center.h -= 5;
  493.     }
  494.  
  495.     /* define region                                                                                    */
  496.     the_end = CDEF_ind_endpt( the_cntl, value );            /* move to end of indicator    */
  497.     SetEmptyRgn ( the_rgn );                                    /* release region memory    */
  498.     OpenRgn();
  499.     LineTo ( base_pt.h, base_pt.v );
  500.     LineTo ( the_center.h, the_center.v );
  501.     LineTo ( the_end.h, the_end.v );
  502.     CloseRgn( the_rgn );                                    /* save region into region passed in        */
  503. }
  504.  
  505. void CDEF_init_cntl ( the_cntl )
  506. ControlHandle    the_cntl;
  507. {
  508.     cntl_rgns_hdl    my_rgns;
  509.     
  510.     /* initialize regions for this control    */
  511.     my_rgns = (cntl_rgns_hdl)NewHandle ( sizeof ( cntl_rgns ) );
  512.     if ( my_rgns != NULL )
  513.     {
  514.         HLock ( (Handle)my_rgns );
  515.         
  516.         (**my_rgns).frame = NewRgn();
  517.         (**my_rgns).empty = NewRgn();
  518.         (**my_rgns).full = NewRgn();
  519.         (**my_rgns).indicator = NewRgn();
  520.         
  521.         HUnlock ( (Handle)my_rgns );
  522.         
  523.         (**the_cntl).contrlData = (Handle)my_rgns;
  524.         CDEF_all_rgns ( the_cntl, (cntl_rgns_hdl)(**the_cntl).contrlData );
  525.     }
  526. }
  527.  
  528.  
  529. void    CDEF_disp_cntl ( the_cntl )
  530. ControlHandle    the_cntl;
  531. {
  532.     cntl_rgns_hdl    my_rgns;
  533.     
  534.     /* dispose of control regions    */
  535.     
  536.     my_rgns = (cntl_rgns_hdl)(**the_cntl).contrlData;
  537.     if ( my_rgns != NULL )
  538.     {
  539.         HLock ( (Handle)my_rgns );
  540.         
  541.         if ( (**my_rgns).frame != NULL )
  542.             DisposeRgn ( (**my_rgns).frame );
  543.         if ( (**my_rgns).full != NULL )
  544.             DisposeRgn ( (**my_rgns).full );
  545.         if ( (**my_rgns).empty != NULL )
  546.             DisposeRgn ( (**my_rgns).empty );
  547.         if ( (**my_rgns).indicator != NULL )
  548.             DisposeRgn ( (**my_rgns).indicator );
  549.             
  550.         HUnlock ( (Handle)my_rgns );
  551.         
  552.         DisposeRgn ( my_rgns );
  553.     }
  554. }
  555.  
  556.  
  557. int32    CDEF_drag_cntl ( the_cntl, param )
  558. ControlHandle    the_cntl;
  559. int32            param;
  560. {
  561.     PenState    ps;
  562.     Rect        ind_rect;
  563.     Point        center, cur_pt, start_pt;
  564.     int16        angle, value;
  565.     RgnHandle    ghost_rgn;
  566.     Pattern        gray_pat;
  567.     
  568.     /* drag either the control or the indicator around    */
  569.     if ( param != NULL )                                /* drag indicator                    */            
  570.     {
  571.         GetPenState ( &ps );                            /* save penstate so we don't have ghosty-ink    */
  572.         
  573.         ghost_rgn = NewRgn ();                            /* region for ghosty indicator outline */
  574.         ind_rect = (**(cntl_rgns_hdl)(**the_cntl).contrlData).ind_rect;
  575.         center = CDEF_find_center ( the_cntl );
  576.         start_pt = CDEF_ind_endpt ( the_cntl, (**the_cntl).contrlValue );
  577.  
  578.         HiliteControl ( the_cntl, inThumb );            /* hilite indicator                    */
  579.  
  580.         /* draw "ghosty-gray" indicator                    */
  581.         PenSize ( 1,1 );
  582.         PenMode ( notPatXor );                            /* this line and the next are the..    */
  583.         GetIndPattern ( &gray_pat, sysPatListID, 4 ); 
  584.         PenPat ( gray_pat );                            /* ghosty-gray ink!!                */
  585.         do                                                 /* drag until user lets go            */
  586.         {
  587.             GetMouse ( &cur_pt );
  588.             PtToAngle ( &ind_rect, cur_pt, &angle );     /* convert cursor position to angle */
  589.             if ( !(angle > 90 && angle < 270) )
  590.             {
  591.                 value = CDEF_angle_to_value ( the_cntl, angle );
  592.                 CDEF_ind_rgn ( the_cntl, value, ghost_rgn );
  593.                 PaintRgn ( ghost_rgn );                    /* paint ghosty-gray indicator        */
  594.                 PaintRgn ( ghost_rgn );                    /* unpaint ghosty-gray indicator    */
  595.             }
  596.         } 
  597.         while ( StillDown () );
  598.         
  599.         PenNormal ();
  600.         (**the_cntl).contrlHilite = 0;
  601.         if ( angle > 90 && angle < 270 )
  602.         {
  603.             SysBeep ( 5 );
  604.             cur_pt = start_pt;
  605.         }
  606.         SubPt ( start_pt, &cur_pt );                    /* pos_cntl expects relative offset        */
  607.         CDEF_pos_cntl ( the_cntl, cur_pt.h, cur_pt.v );    /* move the indicator and update value    */
  608.         DisposeRgn ( ghost_rgn );                        /* release ghosty-gray indicator region    */
  609.         
  610.         SetPenState ( &ps );                            /* restore penstate now we're done    */
  611.         return ( 1L );                                    /* non-null retn means custom drag    */
  612.     }
  613.     else
  614.         return ( NULL );
  615. }
  616.  
  617.     
  618. void    CDEF_pos_cntl ( the_cntl, x, y )
  619. ControlHandle    the_cntl;
  620. int16            x,y;
  621. {
  622.     PenState    ps;
  623.     Rect        ind_rect;
  624.     Point        old_pt, new_pt;
  625.     int16        the_angle;
  626.     uint16        new_value;
  627.     
  628.     /* position the indicator at new location and update contrlValue according                */
  629.     /* to relative offset stored in param field                                                */
  630.     GetPenState ( &ps );
  631.     
  632.     ind_rect = (**(cntl_rgns_hdl)(**the_cntl).contrlData).ind_rect;
  633. /*    EraseOval ( &ind_rect );*/
  634.     
  635.     old_pt = CDEF_ind_endpt( the_cntl, (**the_cntl).contrlValue );        /* moves pen to end of indicator        */
  636.     SetPt ( &new_pt, old_pt.h+x, old_pt.v+y );
  637.     PtToAngle ( &ind_rect, new_pt, &the_angle );    /* get indicator angle based on new_pt    */
  638.     new_value = CDEF_angle_to_value ( the_cntl, the_angle ); /* reset contrlValue to new ind location    */
  639.     (**the_cntl).contrlValue = new_value;
  640.  
  641.     CDEF_ind_rgn ( the_cntl, (**the_cntl).contrlValue, (**(cntl_rgns_hdl)(**the_cntl).contrlData).indicator ); /* recalc region        */
  642.     CDEF_indicator ( the_cntl );                    /* draw indicator in new position        */
  643.     
  644.     SetPenState ( &ps );                            /* reset penstate and get out of Dodge    */
  645. }
  646.  
  647.  
  648. void    CDEF_thumb_cntl    ( the_cntl, param )
  649. ControlHandle    the_cntl;
  650. int32            param;
  651. {
  652.     Rect    temp_rect;
  653.     
  654.     /* calculate limits of movement for the "thumb"                                            */
  655.     temp_rect = (**(cntl_rgns_hdl)(**the_cntl).contrlData).ind_rect;
  656.     temp_rect.bottom = (temp_rect.bottom - temp_rect.top)/2;
  657.     ((thumb_lim *)param)->limitRect = temp_rect;
  658.     ((thumb_lim *)param)->slopRect = temp_rect;
  659.     ((thumb_lim *)param)->axis = NO_CONSTRAINT;
  660. }
  661.